# -*- sh -*-
# Build script to build Puzzles.
#
# You can cut out large components of the build by defining a subset
# of these options on the bob command line:
# -DNOTEST -DNOSIGN -DNOWINDOWS -DNOMACOS -DNOICONS -DNOJAVA -DNOJS

module puzzles

set Version $(!builddate).$(vcsid)

# Put the version number into the documentation as a versionid.
# use perl to avoid inconsistent behaviour of echo '\v'
in puzzles do perl -e 'print "\n\\versionid Simon Tatham'\''s Portable Puzzle Collection, version $$ARGV[0]\n"' $(Version) >> puzzles.but
in puzzles do perl -e 'print "\n\\versionid Simon Tatham'\''s Portable Puzzle Collection, version $$ARGV[0]\n"' $(Version) >> devel.but

# Write out a version.h that contains the real version number.
in puzzles do echo '/* Generated by automated build script */' > version.h
in puzzles do echo '$#define VER "Version $(Version)"' >> version.h
in puzzles do perl -e '$$ARGV[0] =~ m{(....)(..)(..)} or die; print "$#define VERSIONINFO_BINARY_VERSION 1,$$1,$$2,$$3\n"' $(!builddate) >> version.h

# And do the same substitution in the OS X metadata. (This is a bit
# icky in principle because it presumes that my version numbers don't
# need XML escaping, but frankly, if they ever do then I should fix
# them!)
in puzzles do perl -i -pe 's/Unidentified build/$(Version)/' osx/Info.plist

# And in the KaiOS metadata generator.
in puzzles do perl -i -pe 's/Unidentified build/$(Version)/' kaios/manifest.pl

ifneq "$(NOICONS)" yes then
  # Run enough of a native Unix build to produce the various icons.
  # This also checks that the build completes in 'strict' mode (with
  # lots of warnings and -Werror), and triggers a build failure if
  # not.
  in . do cmake -B build-icons puzzles -DSTRICT=ON
  in build-icons do make -j$(nproc)
  in build-icons do make -j$(nproc) icons VERBOSE=1

  # Copy the C icon files into the icons source subdirectory, for the
  # distribution tarball.
  in . do cp build-icons/icons/*-icon.c puzzles/icons
endif

ifneq "$(NOTEST)" yes then
  # Run tests. In particular, ensure we build in 'strict' mode with
  # both gcc and clang.
  ifeq "$(NOICONS)" yes then
    # We don't need to run the gcc build if we did it above for the icons
    in . do cmake -B test-gcc puzzles -DSTRICT=ON
    in test-gcc do make -j$(nproc)
  endif

  in . do cmake -B test-clang puzzles -DSTRICT=ON -DCMAKE_C_COMPILER=clang
  in test-clang do make -j$(nproc)
endif

# The very first thing we do is to make the source archive, before we
# fill up the build directory with extra files.
delegate -
  # Build Windows Help and text versions of the manual for convenience.
  in puzzles do halibut --winhelp=puzzles.hlp --text=puzzles.txt puzzles.but
  # Build a text version of the HACKING document.
  in puzzles do halibut --text=HACKING devel.but
  # Get rid of some cruft that isn't really useful in a source tarball.
  in puzzles do rm -f Buildscr CHECKLST.txt .gitignore webpage.pl
  in . do ln -s puzzles puzzles-$(Version)
  in . do tar -chzf puzzles-$(Version).tar.gz puzzles-$(Version)
  return puzzles-$(Version).tar.gz
enddelegate

ifneq "$(NOMACOS)" yes then
  # Build the OS X binaries and .dmg archive.
  delegate osx
    in puzzles do cmake -B build-osx -DCMAKE_BUILD_TYPE=Release .
    in puzzles/build-osx do make -j$(nproc) package VERBOSE=1
    return puzzles/build-osx/Puzzles.dmg
  enddelegate
endif

ifneq "$(NOWINDOWS)" yes then
  # Build the Windows binaries and installer, and the CHM file.
  in puzzles do make -f Makefile.doc clean
  in puzzles do make -f Makefile.doc -j$(nproc) # build help files for installer

  in . with cmake_at_least_3.20 do cmake -B puzzles/build-win64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_TOOLCHAIN_FILE=$(cmake_toolchain_clangcl64) -DICO_DIR=$$PWD/build-icons/icons puzzles
  in . with cmake_at_least_3.20 do cmake -B puzzles/build-win32 -DCMAKE_BUILD_TYPE=Release -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DCMAKE_TOOLCHAIN_FILE=$(cmake_toolchain_clangcl32) -DICO_DIR=$$PWD/build-icons/icons puzzles
  in puzzles/build-win64 do make -j$(nproc) VERBOSE=1
  in puzzles/build-win32 do make -j$(nproc) VERBOSE=1

  in puzzles do mason.pl --args '{"version":"$(Version)","descfile":"build-win64/gamedesc.txt"}' winwix.mc > puzzles.wxs

  # Code-sign the binaries, if the local bob config provides a script
  # to do so. We assume here that the script accepts an -i option to
  # provide a 'more info' URL, and an optional -n option to provide a
  # program name, and that it can take multiple .exe filename
  # arguments and sign them all in place.
  ifneq "$(cross_winsigncode)" "" then
    in puzzles/build-win64 do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ `cut -f2 -d: gamedesc.txt`
    in puzzles/build-win32 do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ `cut -f2 -d: gamedesc.txt`
  endif

  # Build installers.
  in puzzles with wixonlinux do candle -arch x64 puzzles.wxs -dWin64=yes -dBindir=build-win64/ && light -ext WixUIExtension -sval puzzles.wixobj
  in puzzles with wixonlinux do candle -arch x86 puzzles.wxs -dWin64=no -dBindir=build-win32/ && light -ext WixUIExtension -sval puzzles.wixobj -o puzzles32.msi
  ifneq "$(cross_winsigncode)" "" in puzzles do $(cross_winsigncode) -i https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ -n "Simon Tatham's Portable Puzzle Collection Installer" puzzles.msi puzzles32.msi

  in puzzles do chmod +x build-win32/*.exe build-win64/*.exe
endif

# Build the HTML docs.
in puzzles do mkdir doc
in puzzles do mkdir devel
in puzzles/doc do halibut --html -Chtml-contents-filename:index.html -Chtml-index-filename:indexpage.html -Chtml-template-filename:%k.html -Chtml-template-fragment:%k ../puzzles.but
in puzzles/devel do halibut --html -Chtml-contents-filename:index.html -Chtml-index-filename:indexpage.html -Chtml-template-filename:%k.html -Chtml-template-fragment:%k ../devel.but

ifneq "$(NOWINDOWS)" yes then
  # Move the deliver-worthy Windows binaries (those specified in
  # gamedesc.txt, which is generated by CMakeLists.txt and helpfully
  # excludes the command-line auxiliary utilities such as solosolver,
  # and nullgame.exe) into a subdirectory for easy access.
  in puzzles do mkdir winbin64 winbin32
  in puzzles/build-win64 do mv `cut -f2 -d: gamedesc.txt` ../winbin64
  in puzzles/build-win32 do mv `cut -f2 -d: gamedesc.txt` ../winbin32

  # Make a zip file of the Windows binaries and help files.
  in puzzles do zip -j puzzles.zip winbin64/*.exe puzzles.chm puzzles.hlp puzzles.cnt
  in puzzles do zip -j puzzles32.zip winbin32/*.exe puzzles.chm puzzles.hlp puzzles.cnt
endif

# Build the autogenerated pieces of the main web page.
in puzzles do cmake -B build-gamedesc . -DCMAKE_TOOLCHAIN_FILE=../cmake/windows-dummy-toolchain.cmake
in puzzles do perl webpage.pl build-gamedesc/gamedesc.txt

# Group is playable, even if still a bit unpolished and strange, so we
# can at least make the web versions of it (which are unobtrusive if
# you don't deliberately navigate to the web pages).
set web_unfinished_option -DPUZZLES_ENABLE_UNFINISHED=group

ifneq "$(NOJAVA)" yes then
  # Build the Java applets.
  delegate nestedvm
    in puzzles do cmake -B build-nestedvm -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=../cmake/nestedvm-toolchain.cmake -DNESTEDVM="$$NESTEDVM" $(web_unfinished_option) .
    in puzzles/build-nestedvm do make -j$(nproc) VERBOSE=1
    return puzzles/build-nestedvm/*.jar
    return puzzles/build-nestedvm/unfinished/group.jar
  enddelegate
endif

# Build the Javascript applets. Since my master build machine doesn't
# have the right dependencies installed for Emscripten, I do this by a
# delegation.
ifneq "$(NOJS)" yes then
  # The Emscripten delegate doesn't have Halibut, so build a set of
  # HTML docs for the KaiOS apps to use.
  in puzzles do mkdir -p build-kaios/help/en
  in puzzles/build-kaios/help/en do halibut --html -Chtml-template-fragment:%k ../../../puzzles.but ../../../emcccopy.but
  delegate emscripten
    in puzzles do emcmake cmake -B build-emscripten $(web_unfinished_option) .
    in puzzles/build-emscripten do make -j$(nproc) VERBOSE=1
    return puzzles/build-emscripten/*.js
    return puzzles/build-emscripten/*.wasm
    return puzzles/build-emscripten/unfinished/group.js
    return puzzles/build-emscripten/unfinished/group.wasm
    in puzzles do emcmake cmake -B build-kaios -DWASM=NO -DICON_DIR=$$PWD/../build-icons/icons -DCMAKE_BUILD_TYPE=Release .
    in puzzles/build-kaios do make -j$(nproc) VERBOSE=1 install
    in puzzles/build-kaios/kaios do for p in *; do (cd $$p && zip -rDn .png ../$$p.zip *); done
    return puzzles/build-kaios/kaios/*.zip
  enddelegate

  # Build a set of wrapping HTML pages for easy testing of the
  # Javascript puzzles.
  #
  # These aren't quite the same as the HTML pages that will go on my
  # live website. The live ones will substitute in a different footer
  # that links back to the main puzzles page, and they'll have a
  # different filesystem layout so that ther links to the .js files
  # won't need the ../js/ prefix used below.
  #
  # But these test pages should be good enough to just open after
  # running a build, to make sure the main functionality works.
  # Unfortunately, because JavaScript can't read arbitrary local
  # files, this won't usually work from a file:// URL.  You have to
  # either point an HTTP or HTTPS server at the build output directory
  # or turn off security.fileuri.strict_origin_policy in Firefox.
  in puzzles do mkdir jstest
  in puzzles/jstest do ../html/jspage.pl --jspath=../js/ /dev/null ../html/*.html
endif

# Set up .htaccess containing a redirect for the archive filename.
in puzzles do echo "AddType application/octet-stream .chm" > .htaccess
in puzzles do echo "AddType application/octet-stream .hlp" >> .htaccess
in puzzles do echo "AddType application/octet-stream .cnt" >> .htaccess
in puzzles do echo "AddType application/wasm .wasm" >> .htaccess
in . do set -- puzzles*.tar.gz; echo RedirectMatch temp '(.*/)'puzzles.tar.gz '$$1'"$$1" >> puzzles/.htaccess
in puzzles do echo RedirectMatch temp '(.*/)'puzzles-installer.msi '$$1'puzzles-$(Version)-installer.msi >> .htaccess

# Phew, we're done. Deliver everything!
ifneq "$(NOICONS)" yes then
  deliver build-icons/icons/*-web.png $@
endif
ifneq "$(NOWINDOWS)" yes then
  deliver puzzles/winbin64/*.exe $@
  deliver puzzles/winbin32/*.exe w32/$@
  deliver puzzles/puzzles.zip $@
  deliver puzzles/puzzles32.zip w32/$@
  deliver puzzles/puzzles.msi puzzles-$(Version)-installer.msi
  deliver puzzles/puzzles32.msi w32/puzzles-$(Version)-32bit-installer.msi
  deliver puzzles/puzzles.chm $@
  deliver puzzles/puzzles.hlp $@
  deliver puzzles/puzzles.cnt $@
endif
deliver puzzles/.htaccess $@
deliver puzzles/doc/*.html doc/$@
deliver puzzles/devel/*.html devel/$@
ifneq "$(NOMACOS)" yes then
  deliver puzzles/build-osx/Puzzles.dmg $@
endif
ifneq "$(NOJAVA)" yes then
  deliver puzzles/build-nestedvm/*.jar java/$@
  deliver puzzles/build-nestedvm/unfinished/*.jar java/$@
endif
ifneq "$(NOJS)" yes then
  deliver puzzles/build-emscripten/*.js js/$@
  deliver puzzles/build-emscripten/*.wasm js/$@
  deliver puzzles/build-emscripten/unfinished/*.js js/$@
  deliver puzzles/build-emscripten/unfinished/*.wasm js/$@
  deliver puzzles/jstest/*.html jstest/$@
  deliver puzzles/html/*.html html/$@
  deliver puzzles/html/*.pl html/$@
  deliver puzzles/build-kaios/kaios/*.zip kaios/$@
  ifneq "$(NOICONS)" yes then
    deliver build-icons/icons/*-banner.jpg kaios/$@
  endif
endif
deliver puzzles/wwwspans.html $@
deliver puzzles/wwwlinks.html $@

# deliver puzzles/puzzles.armv4.cab $@ # (not built at the moment)

# This one isn't in the puzzles subdir, because makedist.sh left it
# one level up.
deliver puzzles*.tar.gz $@
